gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/scwinlib/SCMemDC.cpp
//Download by http://www.NewXing.com /* * This file is part of the EMFexplorer projet. * Copyright (C) 2004 Smith Charles. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * Extension: for commercial use, apply the Equity Public License, which * adds to the normal terms of the GLPL a condition of donation to the author. * If you are interested in support for this source code, * contact Smith Charles <smith.charles@free.fr> for more information. */ #include "stdafx.h" #include "SCMemDC.h" #include "SCBitmap.h" #include "SCPalette.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSCMemDC::CSCMemDC(): CDC(), m_hStockBM(NULL), m_pBmpMem(NULL), m_pPal(NULL), m_iWidth(32), m_iHeight(32), m_InitColor(RGB(255,255,255)), m_iGrayScale(STGRAY_SCALE_NONE), m_iGrMode(0) { } CSCMemDC::~CSCMemDC() { // Clean up SCCleanUp(); // delete Windows DC this->DeleteDC(); } void CSCMemDC::SCCleanUp() { // restore and delete palette if (m_pPal) { // reselect the stock palette ::SelectObject(m_hDC, GetStockObject(DEFAULT_PALETTE)); // delete the palette m_pPal->DeleteObject(); delete m_pPal; m_pPal = NULL; } // restore and delete bitmap if (m_pBmpMem) { // reselect the monochrome stock bitmap ASSERT(m_hStockBM); ::SelectObject(m_hDC, m_hStockBM); // now we can delete the bitmap m_pBmpMem->DeleteObject(); delete m_pBmpMem; m_pBmpMem = NULL; } } CBitmap *CSCMemDC::SCDetachDIB() { CBitmap *pBmp = m_pBmpMem; m_pBmpMem = NULL; if (m_hStockBM) { ::SelectObject(m_hDC, m_hStockBM); m_hStockBM = NULL; } return pBmp; } BOOL CSCMemDC::SCPrepareSurface(int width, int height, HENHMETAFILE hemf/*=NULL*/, COLORREF crBkColor/*=RGB(255, 255, 255)*/) { SCCleanUp(); m_iWidth = width; m_iHeight = height; // Create an output compatible DC // if (!m_hDC) if (!CreateCompatibleDC(NULL)) return FALSE; // Use screen DC as compatible output device HBITMAP hbm = NULL; HPALETTE hPalette = NULL; if (m_iGrayScale) hbm = SCCreateGrayScaleDIBSection(NULL, m_iWidth, m_iHeight, m_iGrayScale); else { hbm = SCCreate24BPPDIBSection(NULL, m_iWidth, m_iHeight); if (hemf) hPalette = SCGetEMFPalette(hemf); //else // hPalette = SCGetSystemPalette(); } if (!hbm) { return FALSE; } m_pBmpMem = new CBitmap; m_pBmpMem->Attach(hbm); // Select the bitmap into the off-screen DC. // // Do not use MFC. MFC would return a temporary object linked to the stock bitmap // m_pBmOld = this->SelectObject(m_pBmpMem); // no! // Instead: obtain the stock monochrome bitmap from GDI and save it, as we cant use // GetStockObject for this bitmap. m_hStockBM = (HBITMAP)::SelectObject(m_hDC, hbm); ASSERT(m_hStockBM); // if NULL, GDI failed (maybe memory is low) // Palette management if (hPalette) { m_pPal = new CPalette; m_pPal->Attach(hPalette); CPalette* pPalOld = this->SelectPalette(m_pPal, TRUE); // pPalOld is temporary if (pPalOld) { if (GDI_ERROR == this->RealizePalette()) {// Error management ? // We can grab something (not too pretty) without palette } } // Error management ? // We can grab something (not too pretty) without palette } // Erase the background. // m_InitColor = crBkColor; return SCEraseBkgn(); } BOOL CSCMemDC::SCShrinkSurface(CRect rc) { // Create an output compatible DC // CDC tmpDC; if (!tmpDC.CreateCompatibleDC(NULL)) return FALSE; // Use screen DC as compatible output device HBITMAP hbm = NULL; HPALETTE hPalette = NULL; if (m_iGrayScale) hbm = SCCreateGrayScaleDIBSection(NULL, rc.Width(), rc.Height(), m_iGrayScale); else { hbm = SCCreate24BPPDIBSection(NULL, rc.Width(), rc.Height()); } if (!hbm) return FALSE; CBitmap* pBmp = new CBitmap; pBmp->Attach(hbm); // Select the bitmap into the off-screen DC and init tmp surface. // CBitmap* pBmOld = tmpDC.SelectObject(pBmp); tmpDC.BitBlt(0, 0, rc.Width(), rc.Height(), this, rc.left, rc.top, SRCCOPY); tmpDC.SelectObject(pBmOld); // Swap surfaces this->SelectObject(pBmp); // select new bmp // delete the old one if (m_pBmpMem) { m_pBmpMem->DeleteObject(); delete m_pBmpMem; } m_pBmpMem = pBmp; // new surface size m_iWidth = rc.Width(); m_iHeight = rc.Height(); return TRUE; } BOOL CSCMemDC::SCResetSurfaceColor(int iColor) { if (m_InitColor == iColor) return TRUE; m_InitColor = iColor; return SCEraseBkgn(); } BOOL CSCMemDC::SCEraseBkgn() { CBrush brush; CRect rc(0, 0, m_iWidth, m_iHeight); brush.CreateSolidBrush(m_InitColor); DPtoLP(&rc); FillRect(&rc, &brush); return TRUE; } BOOL CSCMemDC::SCEraseBkgn(CBrush* pBrush) { ASSERT(pBrush); CRect rc(0, 0, m_iWidth, m_iHeight); DPtoLP(&rc); FillRect(&rc, pBrush); return TRUE; } /// /// Rotate and translate DC so that the origin is at (rect.left, rect.top) /// BOOL CSCMemDC::SCRotateDC(int iAngle, CRect rect, int iXPos, int iYPos) { return ::SCRotateDC(m_hDC, iAngle, rect, iXPos, iYPos, m_iGrMode); } /// /// Translate DC so that the origin return at (0, 0) after it was set at (rect.left, rect.top) /// BOOL CSCMemDC::SCRestoreOrigin(int iAngle, CRect rect, int iXPos, int iYPos) { XFORM xform; memset(&xform, 0, sizeof(xform)); xform.eM11 = 1; xform.eM22 = 1; switch (iAngle) { case 90: xform.eDx = (float)(-rect.top + iXPos); xform.eDy = (float)(rect.left + iYPos); break; case 270: xform.eDx = (float)(rect.top + iXPos); xform.eDy = (float)(-rect.left + iYPos); break; case 180: xform.eDx = (float)(-rect.left + iXPos); xform.eDy = (float)(-rect.top + iYPos); break; case 0: xform.eDx = (float)(rect.left + iXPos); xform.eDy = (float)(rect.top + iYPos); break; default: ASSERT(0); } BOOL bOk = ModifyWorldTransform(m_hDC, &xform, MWT_RIGHTMULTIPLY); ASSERT(bOk); return bOk; } BOOL CSCMemDC::SCSelfRotate(int iAngle, CSize sizeDelta) { m_iGrMode = SetGraphicsMode(m_hDC, GM_ADVANCED); ASSERT(m_iGrMode); if (!m_iGrMode) return FALSE; BOOL bOk = FALSE; XFORM xform; memset(&xform, 0, sizeof(xform)); // Save xform XFORM xformSvd; bOk = GetWorldTransform(m_hDC, &xformSvd); ASSERT(bOk); /* translate back to the origin. */ xform.eM11 = xform.eM22 = (float) 1.0; SetWorldTransform (m_hDC, &xform); // rotate switch (iAngle) { case 90: xform.eM11 = 0; xform.eM12 = 1; xform.eDx = (float)(sizeDelta.cy); break; case 270: xform.eM11 = 0; xform.eM12 = -1; xform.eDy = (float)(m_iWidth); break; case 180: xform.eM11 = -1; xform.eM12 = 0; xform.eDy = (float)m_iHeight; xform.eDx = (float)m_iWidth; break; case 0: xform.eM11 = 1; xform.eM12 = 0; break; default: ASSERT(0); } xform.eM22 = xform.eM11; xform.eM21 = -xform.eM12; bOk=ModifyWorldTransform(m_hDC, &xform, MWT_RIGHTMULTIPLY); ASSERT(bOk); /* translate back to the original offset. */ xform.eM11 = xform.eM22 = (float) 1.0; xform.eM12 = xform.eM21 = (float) 0.0; xform.eDx = xformSvd.eDx; xform.eDy = xformSvd.eDy; ModifyWorldTransform (m_hDC, &xform, MWT_RIGHTMULTIPLY); return bOk; } BOOL CSCMemDC::SCUnRotateDC() { return ::SCUnRotateDC(m_hDC, m_iGrMode); } //////////////////////////////////////////////////////////////////////////////////// /// Static /// /// Rotate and translate DC so that the origin is at (rect.left, rect.top) /// BOOL SCRotateDC(HDC hDC, int iAngle, CRect rect, int iXPos, int iYPos, int& iGrOldMode) { iGrOldMode = SetGraphicsMode(hDC, GM_ADVANCED); ASSERT(iGrOldMode); if (!iGrOldMode) return FALSE; BOOL bOk = FALSE; XFORM xform; memset(&xform, 0, sizeof(xform)); // Formulas: //xform.eM11 = (float)cos((float)iAngle*(ST_PI)/180.0f); => 0 for PI/2 and 3PI/2, 1 for 0 and PI //xform.eM12 = (float)sin((float)iAngle*(ST_PI)/180.0f); => 0 for 0 and PI, 1 for PI/2 and 3PI/2 // rotate and translate at once switch (iAngle) { case 90: xform.eM11 = 0; xform.eM12 = 1; xform.eDx = (float)(rect.bottom + iXPos); xform.eDy = (float)(-rect.left + iYPos); break; case 270: xform.eM11 = 0; xform.eM12 = -1; xform.eDx = (float)(-rect.top + iXPos); xform.eDy = (float)(rect.right + iYPos); break; case 180: xform.eM11 = -1; xform.eM12 = 0; xform.eDx = (float)(rect.right + iXPos); xform.eDy = (float)(rect.bottom + iYPos); break; case 0: xform.eM11 = 1; xform.eM12 = 0; xform.eDx = (float)(-rect.left + iXPos); xform.eDy = (float)(-rect.top + iYPos); break; default: ASSERT(0); } xform.eM22 = xform.eM11; xform.eM21 = -xform.eM12; bOk=SetWorldTransform(hDC, &xform); ASSERT(bOk); return bOk; } BOOL SCUnRotateDC(HDC hDC, int iGrOldMode) { if (!iGrOldMode) return FALSE; BOOL bOk = ModifyWorldTransform(hDC, NULL, MWT_IDENTITY); ASSERT(bOk); int iGrMode = SetGraphicsMode(hDC, iGrOldMode); ASSERT(iGrMode); return bOk; } HDC SCGetAttribDC(HDC hDC) { ASSERT(hDC); CDC* pDC = CDC::FromHandle(hDC); return pDC->m_hAttribDC; } ////////////////////////////////////////////////////////////////////////////////////